package com.ds.home.database;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ds.api.GWWebAPI;
import com.ds.common.JDSConstants;
import com.ds.common.cache.Cache;
import com.ds.common.cache.CacheManagerFactory;
import com.ds.common.query.Condition;
import com.ds.common.query.JLuceneIndex;
import com.ds.common.util.Constants;
import com.ds.config.ListResultModel;
import com.ds.context.JDSActionContext;
import com.ds.home.*;
import com.ds.home.database.dao.*;
import com.ds.home.database.manager.EIDBManager;
import com.ds.home.database.vo.*;
import com.ds.home.query.HomeConditionKey;
import com.ds.home.query.IOTConditionKey;
import com.ds.iot.HomeException;
import com.ds.iot.enums.DeviceStatus;
import com.ds.iot.enums.ZNodeZType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

public class MEMManagerImpl implements EIDBManager {
    public static final String THREAD_LOCK = "Thread Lock";
    private static final long DEFAULT_CACHEEXPIRETIME = 7 * 24 * Constants.HOUR;
    private static final Integer DEFAULT_CACHESIZE = 10 * 1024 * 1024;
    private static EIDBManager manager;
    private static final Logger logger = LoggerFactory.getLogger(GWWebAPI.class);
    private Cache<String, AreaVO> areaCache;
    private Cache<String, PlaceVO> placeCache;

    private Cache<String, SensortypeVO> sensorTypeNoCache;
    private Cache<String, SensortypeVO> sensorTypeIdCache;
    private Cache<String, AlarmVO> alarmCache;
    private Cache<String, SceneVO> sceneCache;

    private String cacheKey = JDSConstants.ORGCONFIG_KEY;

    // private String cacheKey=OrgConstants.CONFIG_KEY;

    Cache<String, DeviceVO> deviceCache;

    Cache<String, String> deviceSerialnoCache;

    //Cache<String, List<String>> areaDeviceIdCache;

    // Cache<String, List<String>> placeDeviceIdCache;

    Cache<String, DeviceEndPointVO> endPointCache;

    Cache<String, String> endPointSerialnoCache;
    Cache<String, String> devicemacadressCache;
    Cache<String, String> allEPIdCache;
    Cache<String, String> allChildIdCache;

    Cache<String, ZNodeVO> znodeCache;

    private Cache<String, String> currValueCache;

    private Cache<String, String> allZNodeIdCache;

    private Cache<String, String> placeRefChildIdCache;

    private Cache<String, String> allAreaIdCache;

    private Cache<String, String> zNodeRefZNodeCache;

    private Cache<String, String> zNodeRefAlarmCache;

    private Cache<String, String> allSceneIdCache;

    public synchronized static EIDBManager getInstance() {
        if (manager == null) {
            synchronized (THREAD_LOCK) {
                manager = new MEMManagerImpl();
            }
        }
        return manager;
    }

    MEMManagerImpl() {

        zNodeRefZNodeCache = CacheManagerFactory.createCache(cacheKey, "ZNodeRefZNodeCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);
        zNodeRefAlarmCache = CacheManagerFactory.createCache(cacheKey, "ZNodeRefAlarmCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);
        allSceneIdCache = CacheManagerFactory.createCache(cacheKey, "ZNodeRefSceneCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        allAreaIdCache = CacheManagerFactory.createCache(cacheKey, "PlaceRefAreaCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        placeRefChildIdCache = CacheManagerFactory.createCache(cacheKey, "PlaceRefChildIdCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        currValueCache = CacheManagerFactory.createCache(cacheKey, "EndPointCurrValueCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        allZNodeIdCache = CacheManagerFactory.createCache(cacheKey, "AllZNodeIdCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        allEPIdCache = CacheManagerFactory.createCache(cacheKey, "DeviceRefPointCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        allChildIdCache = CacheManagerFactory.createCache(cacheKey, "DeviceRefDeviceCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        areaCache = CacheManagerFactory.createCache(cacheKey, "AreaCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        alarmCache = CacheManagerFactory.createCache(cacheKey, "AlarmCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        placeCache = CacheManagerFactory.createCache(cacheKey, "PlaceCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        sensorTypeNoCache = CacheManagerFactory.createCache(cacheKey, "SensorTypeNoCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        sensorTypeIdCache = CacheManagerFactory.createCache(cacheKey, "SensorTypeIdCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        sceneCache = CacheManagerFactory.createCache(cacheKey, "SceneCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        endPointCache = CacheManagerFactory.createCache(cacheKey, "EndPointCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        endPointSerialnoCache = CacheManagerFactory.createCache(cacheKey, "EndPointSerialnoCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        deviceCache = CacheManagerFactory.createCache(cacheKey, "DeviceCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        deviceSerialnoCache = CacheManagerFactory.createCache(cacheKey, "DeviceSerialnoCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        //areaDeviceIdCache = CacheManagerFactory.createCache(cacheKey, "AreaDeviceIdCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        //placeDeviceIdCache = CacheManagerFactory.createCache(cacheKey, "PlaceDeciceIdCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        devicemacadressCache = CacheManagerFactory.createCache(cacheKey, "DevicemacadressCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);

        znodeCache = CacheManagerFactory.createCache(cacheKey, "ZnodeCache", DEFAULT_CACHESIZE, DEFAULT_CACHEEXPIRETIME);
    }

    public EIPlace getPlaceById(String placeId) {
        if (placeId == null) {
            return null;
        }
        PlaceVO placeVO = placeCache.get(placeId);
        if (placeVO == null) {
            PlaceDAO placeDAO = new PlaceDAO();
            placeVO = placeDAO.findById(placeId);
            if (placeVO == null) {
                return null;
            }

            placeCache.put(placeId, placeVO);
        }

        return new DBPlace(placeVO);
    }

    public List<EIPlace> findPlaceByPersonId(String userid) {
        PlaceDAO placeDAO = new PlaceDAO();
        List<PlaceVO> placeList = placeDAO.findByUserid(userid);
        List<EIPlace> places = new ArrayList<EIPlace>();
        for (PlaceVO place : placeList) {
            places.add(this.getPlaceById(place.getPlaceid()));
        }
        return places;
    }

    public List<EIPlace> findPlaceByOrgId(String orgid) {
        PlaceDAO placeDAO = new PlaceDAO();
        List<PlaceVO> placeList = placeDAO.findByOrgid(orgid);
        List<EIPlace> places = new ArrayList<EIPlace>();
        for (PlaceVO place : placeList) {
            places.add(this.getPlaceById(place.getPlaceid()));
        }
        return places;
    }

    public List<EIPlace> findAllPersonPlace() {
        PlaceDAO placeDAO = new PlaceDAO();
        List<PlaceVO> placeList = placeDAO.findAllUserPlace();
        List<EIPlace> places = new ArrayList<EIPlace>();
        for (PlaceVO place : placeList) {
            places.add(this.getPlaceById(place.getPlaceid()));
        }
        return places;
    }


    public List<EIPlace> findAllOrgPlace() {
        PlaceDAO placeDAO = new PlaceDAO();
        List<PlaceVO> placeList = placeDAO.findAllOrgPlace();
        List<EIPlace> places = new ArrayList<EIPlace>();
        for (PlaceVO place : placeList) {
            places.add(this.getPlaceById(place.getPlaceid()));
        }
        return places;
    }

    public EIArea createArea(String name, String placeId) {
        AreaDAO areaDAO = new AreaDAO();
        AreaVO area = new AreaVO();
        area.setAreaid(UUID.randomUUID().toString());
        area.setName(name);
        area.setPlaceid(placeId);
        areaDAO.insert(area);
        EIArea proxy = new DBArea(area);
        areaCache.put(area.getAreaid(), area);
        return proxy;
    }

    public EIArea getAreaById(String areaId) {
        EIArea area = null;
        AreaVO areavo = areaCache.get(areaId);
        if (areavo == null) {
            AreaDAO areaDAO = new AreaDAO();
            areavo = areaDAO.findById(areaId);
            areaCache.put(areaId, areavo);
        }
        if (areavo != null) {
            area = new DBArea(areavo);
        }

        return area;
    }

    public ListResultModel<Set<String>> findPlace(Condition<HomeConditionKey, JLuceneIndex> condition) {
        ListResultModel<Set<String>> result = new ListResultModel<Set<String>>();
        Set<String> ids = new LinkedHashSet<String>();
        PlaceDAO placeDAO = new PlaceDAO();
        String where = "";
        if (condition != null) {
            String conditionStr = condition.makeConditionString();
            if (conditionStr != null && !conditionStr.equals("")) {
                where = " where " + conditionStr;
            }
        }

        int pageIndex = condition.getPage().getPageIndex();
        int pageSize = condition.getPage().getPageSize();
        List<PlaceVO> placevos = placeDAO.loadByWhere(where);
        if (pageIndex < 1) {
            pageIndex = 1;
        }

        int start = (pageIndex - 1) * pageSize;
        int end = pageSize * pageIndex;
        if (end > placevos.size()) {
            end = placevos.size();
        }
        for (int k = start; k < end; k++) {
            PlaceVO placevo = placevos.get(k);
            ids.add(placevo.getPlaceid());
        }
        result.setSize(placevos.size());
        result.setData(ids);


        return result;

    }

    public ListResultModel<Set<String>> findArea(Condition<HomeConditionKey, JLuceneIndex> condition) {
        ListResultModel<Set<String>> result = new ListResultModel<Set<String>>();
        Set<String> objs = new LinkedHashSet<>();
        AreaDAO areaDAO = new AreaDAO();

        String where = "";
        if (condition != null) {
            String conditionStr = condition.makeConditionString();
            if (conditionStr != null && !conditionStr.equals("")) {
                where = " where " + conditionStr;
            }
        }

        int pageIndex = condition.getPage().getPageIndex();
        int pageSize = condition.getPage().getPageSize();
        List<AreaVO> vos = areaDAO.loadByWhere(where);
        if (pageIndex < 1) {
            pageIndex = 1;
        }

        int start = (pageIndex - 1) * pageSize;
        int end = pageSize * pageIndex;
        if (end > vos.size()) {
            end = vos.size();
        }
        for (int k = start; k < end; k++) {
            AreaVO vo = vos.get(k);
            objs.add(vo.getAreaid());
        }
        result.setSize(vos.size());
        result.setData(objs);


        return result;
    }


    public ListResultModel<Set<String>> findDevice(Condition<IOTConditionKey, JLuceneIndex> condition) {
        ListResultModel<Set<String>> result = new ListResultModel<Set<String>>();
        Set<String> objs = new LinkedHashSet<>();
        DeviceDAO deviceDAO = new DeviceDAO();

        String where = "";
        if (condition != null) {
            String conditionStr = condition.makeConditionString();
            if (conditionStr != null && !conditionStr.equals("")) {
                where = " where " + conditionStr;
            }
        }

        int pageIndex = condition.getPage().getPageIndex();
        int pageSize = condition.getPage().getPageSize();
        List<DeviceVO> vos = deviceDAO.loadByWhere(where);
        if (pageIndex < 1) {
            pageIndex = 1;
        }

        int start = (pageIndex - 1) * pageSize;
        int end = pageSize * pageIndex;
        if (end > vos.size()) {
            end = vos.size();
        }
        for (int k = start; k < end; k++) {
            DeviceVO vo = vos.get(k);
            objs.add(vo.getDeviceid());
        }
        result.setSize(vos.size());
        result.setData(objs);


        return result;
    }


    public ListResultModel<Set<String>> findEndPoint(Condition<IOTConditionKey, JLuceneIndex> condition) {
        ListResultModel<Set<String>> result = new ListResultModel<Set<String>>();
        Set<String> objs = new LinkedHashSet<>();
        DeviceEndPointDAO deviceEndPointDAO = new DeviceEndPointDAO();

        String where = "";
        if (condition != null) {
            String conditionStr = condition.makeConditionString();
            if (conditionStr != null && !conditionStr.equals("")) {
                where = " where " + conditionStr;
            }
        }

        int pageIndex = condition.getPage().getPageIndex();
        int pageSize = condition.getPage().getPageSize();
        List<DeviceEndPointVO> vos = deviceEndPointDAO.loadByWhere(where);
        if (pageIndex < 1) {
            pageIndex = 1;
        }

        int start = (pageIndex - 1) * pageSize;
        int end = pageSize * pageIndex;
        if (end > vos.size()) {
            end = vos.size();
        }
        for (int k = start; k < end; k++) {
            DeviceEndPointVO vo = vos.get(k);
            objs.add(vo.getEndPointId());
        }
        result.setSize(vos.size());
        result.setData(objs);


        return result;
    }

    public ListResultModel<Set<String>> findZNode(Condition<IOTConditionKey, JLuceneIndex> condition) {
        ListResultModel<Set<String>> result = new ListResultModel<Set<String>>();
        Set<String> objs = new LinkedHashSet<String>();
        ZNodeDAO znodeDAO = new ZNodeDAO();

        String where = "";
        if (condition != null) {
            String conditionStr = condition.makeConditionString();
            if (conditionStr != null && !conditionStr.equals("")) {
                where = " where " + conditionStr;
            }
        }

        int pageIndex = condition.getPage().getPageIndex();
        int pageSize = condition.getPage().getPageSize();
        List<ZNodeVO> vos = znodeDAO.loadByWhere(where);
        if (pageIndex < 1) {
            pageIndex = 1;
        }

        int start = (pageIndex - 1) * pageSize;
        int end = pageSize * pageIndex;
        if (end > vos.size()) {
            end = vos.size();
        }
        for (int k = start; k < end; k++) {
            ZNodeVO vo = vos.get(k);
            objs.add(vo.getZnodeid());
        }
        result.setSize(vos.size());
        result.setData(objs);


        return result;
    }

    public ListResultModel<Set<String>> findAlarm(Condition<HomeConditionKey, JLuceneIndex> condition) {
        ListResultModel<Set<String>> result = new ListResultModel<Set<String>>();
        Set<String> objs = new LinkedHashSet<String>();
        AlarmDAO alarmDAO = new AlarmDAO();

        String where = "";
        if (condition != null) {
            String conditionStr = condition.makeConditionString();
            if (conditionStr != null && !conditionStr.equals("")) {
                where = " where " + conditionStr;
            }
        }

        int pageIndex = condition.getPage().getPageIndex();
        int pageSize = condition.getPage().getPageSize();
        List<AlarmVO> vos = alarmDAO.loadByWhere(where);
        if (pageIndex < 1) {
            pageIndex = 1;
        }

        int start = (pageIndex - 1) * pageSize;
        int end = pageSize * pageIndex;
        if (end > vos.size()) {
            end = vos.size();
        }
        for (int k = start; k < end; k++) {
            AlarmVO vo = vos.get(k);
            objs.add(vo.getAlarmid());
        }
        result.setSize(vos.size());
        result.setData(objs);


        return result;
    }

    @Override
    public ListResultModel<Set<String>> findScene(Condition<HomeConditionKey, JLuceneIndex> condition) {
        ListResultModel<Set<String>> result = new ListResultModel<Set<String>>();
        Set<String> objs = new LinkedHashSet<>();
        SceneDAO sceneDAO = new SceneDAO();

        String where = "";
        if (condition != null) {
            String conditionStr = condition.makeConditionString();
            if (conditionStr != null && !conditionStr.equals("")) {
                where = " where " + conditionStr;
            }
        }

        int pageIndex = condition.getPage().getPageIndex();
        int pageSize = condition.getPage().getPageSize();
        List<SceneVO> vos = sceneDAO.loadByWhere(where);
        if (pageIndex < 1) {
            pageIndex = 1;
        }

        int start = (pageIndex - 1) * pageSize;
        int end = pageSize * pageIndex;
        if (end > vos.size()) {
            end = vos.size();
        }
        for (int k = start; k < end; k++) {
            SceneVO vo = vos.get(k);
            objs.add(vo.getSceneid());
        }
        result.setSize(vos.size());
        result.setData(objs);


        return result;

    }


    public EIPlace createPlace(String name, String parentId, String personId) {
        PlaceDAO placeDAO = new PlaceDAO();
        PlaceVO placevo = new PlaceVO();
        placevo.setPlaceid(UUID.randomUUID().toString());
        placevo.setName(name);
        placevo.setUserid(personId);
        placevo.setParentid(parentId);
        placeDAO.insert(placevo);

        EIPlace place = new DBPlace(placevo);
        placeCache.put(placevo.getPlaceid(), placevo);
        return place;
    }

    public void deleteAreaById(String areaId) {
        AreaDAO areaDAO = new AreaDAO();
        AreaVO area = areaDAO.findById(areaId);
        if (area != null) {
            areaDAO.delete(area);
            areaCache.remove(areaId);
        }

    }

    public void deletePlaceById(String placeId) {
        PlaceDAO placeDAO = new PlaceDAO();
        PlaceVO place = placeDAO.findById(placeId);
        if (place != null) {
            placeDAO.delete(place);
            placeCache.remove(placeId);
        }

    }

    public List<EIArea> getAreasByPersonId(String userid) {
        List<EIPlace> places = this.findPlaceByPersonId(userid);
        List<EIArea> areas = new ArrayList<EIArea>();
        for (EIPlace place : places) {
            areas.addAll(getAreasByPlaceId(place.getPlaceid()));
        }
        return areas;
    }

    public EIArea getAreaByname(String name, String placeId) {
        List<EIArea> areas = this.getAreasByPlaceId(placeId);
        for (EIArea area : areas) {
            if (area.getName().equals(name)) {
                return area;
            }
        }
        return null;
    }

    public void updateArea(EIArea area) {
        AreaDAO areaDAO = new AreaDAO();
        DBArea dbarea = (DBArea) area;
        areaDAO.update(dbarea.getVo());
        areaCache.put(area.getAreaid(), dbarea.getVo());
    }

//    public List<EIPlace> findPlaceByName(String name, String userId) {
//        List<EIPlace> places = new ArrayList<EIPlace>();
//        PlaceDAO placeDAO = new PlaceDAO();
//        PlaceVO sameplace = new PlaceVO();
//        sameplace.setName(name);
//        sameplace.setUserid(userId);
//        List<PlaceVO> placevos = placeDAO.findByExample(sameplace);
//        for (PlaceVO place : placevos) {
//            places.add(this.getPlaceById(place.getPlaceid()));
//        }
//
//        return places;
//    }

    public List<EIPlace> findPlaceByName(String name, String parentId, String userId) {
        List<EIPlace> places = new ArrayList<EIPlace>();
        PlaceDAO placeDAO = new PlaceDAO();
        PlaceVO sameplace = new PlaceVO();
        sameplace.setName(name);
        sameplace.setUserid(userId);
        sameplace.setParentid(parentId);
        List<PlaceVO> placevos = placeDAO.findByExample(sameplace);
        for (PlaceVO place : placevos) {
            places.add(this.getPlaceById(place.getPlaceid()));
        }

        return places;
    }

    public void deleteAlarmById(String alarmId) {
        AlarmDAO alarmDAO = new AlarmDAO();
        EIAlarm alarm = this.getAlarmById(alarmId);
        alarm.getZNode().removeAlarm(alarmId);

        AlarmVO alarmvo = alarmDAO.findById(alarmId);
        if (alarmvo != null) {
            alarmDAO.delete(alarmvo);
            this.alarmCache.remove(alarmId);
        }

    }

    public EIAlarm getAlarmById(String alarmId) {
        AlarmVO alarmvo = alarmCache.get(alarmId);
        if (alarmvo == null) {
            AlarmDAO alarmDAO = new AlarmDAO();
            alarmvo = alarmDAO.findById(alarmId);
            alarmCache.put(alarmId, alarmvo);
        }
        return this.getAlarmById(alarmvo.getAlarmid());
    }

    public List<EISensortype> getSensorTypeByDeivceId(String deviceid) {
        SensortypeDAO sensortypeDAO = new SensortypeDAO();

        List<EISensortype> types = new ArrayList<EISensortype>();

        List<SensortypeVO> typevos = sensortypeDAO.findByDeviceid(deviceid);
        for (SensortypeVO vo : typevos) {
            types.add(this.getSensoTypeById(vo.getTypeid()));

        }

        return types;
    }

    public void updateAlarm(EIAlarm alarm) {
        if (alarm != null) {
            AlarmDAO alarmDAO = new AlarmDAO();
            alarm.getZNode().addAlarm(alarm);

            DBAlarm dbalarm = (DBAlarm) alarm;
            alarmDAO.update(dbalarm.getVo());
            alarmCache.put(alarm.getAlarmid(), dbalarm.getVo());
        }

    }

    public void deleteScene(String sceneId) {
        SceneDAO sceneDAO = new SceneDAO();

        EIScene scene = this.getSceneById(sceneId);
        scene.getZnode().removeScene(sceneId);

        SceneVO scenevo = sceneDAO.findById(sceneId);
        if (scenevo != null) {
            sceneDAO.delete(scenevo);
            sceneCache.remove(scene.getSceneid());
        }
    }

    public EIScene getSceneById(String sceneId) {
        SceneVO scenevo = sceneCache.get(sceneId);
        if (scenevo == null) {
            SceneDAO sceneDAO = new SceneDAO();
            scenevo = sceneDAO.findById(sceneId);
            sceneCache.put(sceneId, scenevo);
        }
        return this.getSceneById(scenevo.getSceneid());
    }

    public void updateScene(EIScene scene) {

        SceneDAO sceneDAO = new SceneDAO();

        sceneDAO.update(((DBScene) scene).getVo());

        sceneCache.put(scene.getSceneid(), ((DBScene) scene).getVo());

    }

    public EISensortype getSensoTypeByNo(Integer no) {

        SensortypeVO typevo = sensorTypeNoCache.get(no.toString());
        EISensortype type = null;
        if (typevo == null) {
            SensortypeDAO sensortypeDAO = new SensortypeDAO();
            List<SensortypeVO> vos = sensortypeDAO.findBynO(no);
            if (vos.size() > 0) {
                SensortypeVO vo = sensortypeDAO.findBynO(no).get(0);
                type = this.getSensoTypeById(vo.getTypeid());
                sensorTypeNoCache.put(no.toString(), vo);
            }

        } else {
            type = this.getSensoTypeById(typevo.getTypeid());
        }

        return type;
    }

    public List<EIAlarm> getAlarmsBySensorId(String sensorId) {
        AlarmDAO alarmDAO = new AlarmDAO();
        List<EIAlarm> cachealarms = new ArrayList<EIAlarm>();
        List<AlarmVO> alarms = alarmDAO.findBySensorId(sensorId);
        for (AlarmVO alarm : alarms) {
            cachealarms.add(this.getAlarmById(alarm.getAlarmid()));
        }
        return cachealarms;
    }

    public List<EIScene> getScenesBySensorId(String sensorId) {
        SceneDAO sceneDAO = new SceneDAO();
        List<EIScene> cachescenes = new ArrayList<EIScene>();
        List<SceneVO> scenes = sceneDAO.findBySensorId(sensorId);
        for (SceneVO scene : scenes) {
            cachescenes.add(this.getSceneById(scene.getSceneid()));
        }
        return cachescenes;
    }

    public EIAlarm creatAlarm(String sensorId) {
        AlarmDAO alarmDAO = new AlarmDAO();
        AlarmVO alarmvo = new AlarmVO();
        alarmvo.setAlarmid(UUID.randomUUID().toString());
        alarmvo.setSensorid(sensorId);
        alarmDAO.insert(alarmvo);
        EIAlarm alarm = new DBAlarm(alarmvo);

        alarm.getZNode().addAlarm(alarm);
        alarmCache.put(alarmvo.getAlarmid(), alarmvo);

        return alarm;
    }

    public EIScene creatScene(String sensorId) {

        SceneVO scenevo = new SceneVO();
        scenevo.setSceneid(UUID.randomUUID().toString());
        scenevo.setSensorid(sensorId);
        EIScene scene = new DBScene(scenevo);

        scene.getZnode().addScene(scene);
        sceneCache.put(scene.getSceneid(), scenevo);
        return scene;
    }

    public EISensortype getSensoTypeById(String sensortypeId) {
        SensortypeVO sceneTypevo = sensorTypeIdCache.get(sensortypeId);
        EISensortype sensortype = null;
        if (sceneTypevo == null) {
            SensortypeDAO sensortypeDAO = new SensortypeDAO();
            sceneTypevo = sensortypeDAO.findById(sensortypeId);

            sensorTypeIdCache.put(sensortypeId, sceneTypevo);
            sensorTypeNoCache.put(sceneTypevo.getType().toString(), sceneTypevo);
        }
        sensortype = new DBSensortype(sceneTypevo);
        return sensortype;
    }

    public List<EIDevice> findDeviceByChannel(String channel) {

        DeviceDAO devicedao = new DeviceDAO();

        List<EIDevice> deviceList = new ArrayList<EIDevice>();
        List<DeviceVO> devicevoList = devicedao.findByChannel(channel);

        for (DeviceVO vo : devicevoList) {
            deviceList.add(this.getDeviceById(vo.getDeviceid()));
        }

        return deviceList;
    }

    public List<EIDevice> findDeviceByArea(String areaId) {
        DeviceDAO devicedao = new DeviceDAO();
        List<EIDevice> devices = new ArrayList<EIDevice>();

        List<String> deviceIds = new ArrayList<String>();
        List<DeviceVO> deviceList = devicedao.findByAreaId(areaId);
        for (DeviceVO vo : deviceList) {
            deviceIds.add(vo.getDeviceid());
        }
//
//
//        List<String> deviceIds = areaDeviceIdCache.get(areaId);
//
//        if (deviceIds == null) {
//            deviceIds = new ArrayList<String>();
//            List<DeviceVO> deviceList = devicedao.findByAreaId(areaId);
//            for (DeviceVO vo : deviceList) {
//                deviceIds.add(vo.getDeviceid());
//            }
//            if (!deviceIds.isEmpty()) {
//                areaDeviceIdCache.put(areaId, deviceIds);
//            }
//        }

        for (String deviceId : deviceIds) {
            devices.add(this.getDeviceById(deviceId));
        }

        return devices;
    }

    public List<EIDevice> findDeviceByPlace(String placeId) {
        DeviceDAO devicedao = new DeviceDAO();
        List<EIDevice> devices = new ArrayList<EIDevice>();

        List<DeviceVO> deviceList = devicedao.findByPlaceId(placeId);
        for (DeviceVO vo : deviceList) {
            devices.add(this.getDeviceById(vo.getDeviceid()));
        }
//        List<String> deviceIds = placeDeviceIdCache.get(placeId);
//        List<String> deviceIds = placeDeviceIdCache.get(placeId);
//
//        if (deviceIds == null) {
//            deviceIds = new ArrayList<String>();
//            List<DeviceVO> deviceList = devicedao.findByPlaceId(placeId);
//            for (DeviceVO vo : deviceList) {
//                deviceIds.add(vo.getDeviceid());
//            }
//            if (!deviceIds.isEmpty()) {
//                placeDeviceIdCache.put(placeId, deviceIds);
//            }
//        }
//
//        for (String deviceId : deviceIds) {
//            devices.add(this.getDeviceById(deviceId));
//        }

        return devices;
    }

    /**
     * 根据设备串号获取设备
     *
     * @param serialno
     * @return
     */
    public EIDevice getDeviceBySerialno(String serialno) {

        String deviceId = deviceSerialnoCache.get(serialno);
        EIDevice device = null;
        if (deviceId != null) {
            device = this.getDeviceById(deviceId);
        } else {
            DeviceDAO devicedao = new DeviceDAO();

            List<DeviceVO> deviceList = devicedao.findBySerialno(serialno);

            if (deviceList.size() > 0) {
                device = this.getDeviceById(deviceList.get(0).getDeviceid());
                if (device.getMacaddress() != null) {
                    devicemacadressCache.put(device.getMacaddress(), device.getDeviceid());
                }

                if (device.getSerialno() != null) {
                    deviceSerialnoCache.put(device.getSerialno(), device.getDeviceid());
                }
                deviceCache.put(device.getDeviceid(), deviceList.get(0));
            }

        }
        return device;
    }

    public EIDevice getDeviceByMacaddress(String macaddress) {

        String deviceId = devicemacadressCache.get(macaddress);
        EIDevice device = null;
        if (deviceId != null) {
            device = this.getDeviceById(deviceId);
        } else {
            DeviceDAO devicedao = new DeviceDAO();
            List<DeviceVO> deviceList = devicedao.findByMacaddress(macaddress);

            if (deviceList.size() > 0) {
                device = this.getDeviceById(deviceList.get(0).getDeviceid());
                if (device.getMacaddress() != null) {
                    devicemacadressCache.put(device.getMacaddress(), device.getDeviceid());
                }

                if (device.getSerialno() != null) {
                    deviceSerialnoCache.put(device.getSerialno(), device.getDeviceid());
                }

                deviceCache.put(device.getDeviceid(), deviceList.get(0));
            }
            // devicedao.getSession().close();
        }
        return device;
    }

    public EIDevice getDeviceById(String id) {
        DeviceVO devicevo = deviceCache.get(id);
        EIDevice device = null;
        if (devicevo == null) {
            DeviceDAO devicedao = new DeviceDAO();
            devicevo = devicedao.findById(id);
            if (devicevo != null) {
                device = new DBDevice(devicevo);
                devicemacadressCache.put(device.getMacaddress(), device.getDeviceid());
                if (device.getSerialno() != null) {
                    deviceSerialnoCache.put(device.getSerialno(), device.getDeviceid());
                }
                deviceCache.put(device.getDeviceid(), devicevo);
            }

        } else {
            device = new DBDevice(devicevo);
        }
        return device;
    }

    public void updateDevice(EIDevice device) {
        updateDevice(device, true);
    }

    public void updateDevice(EIDevice device, boolean isdb) {
        DeviceDAO devicedao = new DeviceDAO();
        DBDevice dbdevice = (DBDevice) device;

        if (isdb) {
            devicedao.update(dbdevice.getDevicevo());
            List<EIDeviceEndPoint> endpoints = device.getDeviceEndPoints();
            for (EIDeviceEndPoint endPoint : endpoints) {
                this.updateEndPoint(endPoint);
            }
        }

        if (device.getMacaddress() != null) {
            devicemacadressCache.put(device.getMacaddress(), device.getDeviceid());
        }


        deviceCache.put(device.getDeviceid(), dbdevice.getDevicevo());
        if (device.getSerialno() != null) {
            deviceSerialnoCache.put(device.getSerialno(), device.getDeviceid());
        }

    }

    public List<EIDevice> getDevicesByBindAccount(String bindingaccount) {
        DeviceDAO devicedao = new DeviceDAO();
        List<EIDevice> deviceList = new ArrayList<EIDevice>();
        List<DeviceVO> devicevoList = devicedao.findByBindingaccount(bindingaccount);

        for (DeviceVO vo : devicevoList) {
            deviceList.add(this.getDeviceById(vo.getDeviceid()));
        }

        return deviceList;
    }

    public EIDeviceEndPoint getEPBySerialno(String serialno) {
        DeviceEndPointDAO dao = new DeviceEndPointDAO();
        EIDeviceEndPoint ep = null;

        String epid = endPointSerialnoCache.get(serialno);
        if (epid != null) {
            ep = this.getEndPoindById(epid);
        }
        if (ep == null) {
            List<DeviceEndPointVO> epList = dao.findByIeeeaddress(serialno);
            for (DeviceEndPointVO epvo : epList) {
                // if (epvo.getDeviceId() != null && epvo.getDeviceId().equals(deviceId)) {
                ep = this.getEndPoindById(epvo.getEndPointId());
                endPointCache.put(epid, epvo);
                endPointSerialnoCache.put(serialno, ep.getEndPointId());
                // }
            }
        }
        return ep;
    }

    public List<EIDeviceEndPoint> getEndPointsByDeviceId(String deviceId) {
        DeviceEndPointDAO dao = new DeviceEndPointDAO();
        List<EIDeviceEndPoint> eps = new ArrayList<EIDeviceEndPoint>();

        List<DeviceEndPointVO> vos = dao.findByDeviceId(deviceId);
        for (DeviceEndPointVO vo : vos) {
            eps.add(this.getEndPoindById(vo.getEndPointId()));
        }
        return eps;
    }

    public EIDeviceEndPoint getEndPoindById(String endPointId) {
        DeviceEndPointDAO dao = new DeviceEndPointDAO();
        DeviceEndPointVO epvo = endPointCache.get(endPointId);
        EIDeviceEndPoint ep = null;
        if (epvo == null) {
            epvo = dao.findById(endPointId);
            if (epvo != null) {
                endPointCache.put(endPointId, epvo);
                String key = epvo.getDeviceId() + "[" + epvo.getIeeeaddress() + "]";
                endPointSerialnoCache.put(key, epvo.getEndPointId());
            }
        }
        if (epvo != null) {
            ep = new DBDeviceEndPoint(epvo);
        }
        return ep;
    }

    public void updateEndPoint(EIDeviceEndPoint endPoint) {
        updateEndPoint(endPoint, true);
    }

    public void updateEndPoint(EIDeviceEndPoint endPoint, boolean indb) {
        EIDevice device = endPoint.getDevice();
        device.addEndPoint(endPoint);

        // List<EIZNode> znodes=endPoint.getAllZNodes();
        // for(EIZNode znode:znodes){
        // this.updateZNode(znode);
        // }
        DBDeviceEndPoint dbEndPoint = (DBDeviceEndPoint) endPoint;
        if (indb) {

            DeviceEndPointDAO dao = new DeviceEndPointDAO();

            dao.update(dbEndPoint.getVo());
        }

        endPointCache.put(endPoint.getEndPointId(), dbEndPoint.getVo());

        endPointSerialnoCache.put(endPoint.getIeeeaddress(), endPoint.getEndPointId());

    }

    public EIDeviceEndPoint createEndPoint(String deviceId, String ieeeAddress, String ep, Integer sensorType, String name) {

        DeviceEndPointVO vo = new DeviceEndPointVO();
        vo.setEndPointId(UUID.randomUUID().toString());
        vo.setDeviceId(deviceId);
        vo.setEp(ep);
        vo.setIeeeaddress(ieeeAddress);
        vo.setSensorType(sensorType);
        vo.setName(name);
        DeviceEndPointDAO dao = new DeviceEndPointDAO();
        dao.insert(vo);
        endPointCache.put(vo.getEndPointId(), vo);
        EIDeviceEndPoint endPoint = new DBDeviceEndPoint(vo);

        String key = vo.getDeviceId() + "[" + vo.getIeeeaddress() + "]";

        endPointSerialnoCache.put(endPoint.getIeeeaddress(), endPoint.getEndPointId());

        return endPoint;

    }

    public void deleteEndPoint(String endPointId) {
        DeviceEndPointDAO dao = new DeviceEndPointDAO();
        EIDeviceEndPoint endPoint = this.getEndPoindById(endPointId);

        DeviceEndPointVO endPointVO = dao.findById(endPointId);

        EIDevice device = endPoint.getDevice();

        device.removeEndPoint(endPointId);

        List<EIZNode> endPoints = endPoint.getAllZNodes();

        for (EIZNode znode : endPoints) {
            this.deleteZNodeById(znode.getZnodeid());
        }

        endPointCache.remove(endPoint);

        String key = endPoint.getDevice().getDeviceid() + "[" + endPoint.getIeeeaddress() + "]";

        endPointSerialnoCache.put(endPoint.getIeeeaddress(), endPoint.getEndPointId());

        dao.delete(endPointVO);
    }

    public void deleteDevice(String deviceId) {
        DeviceDAO devicedao = new DeviceDAO();

        EIDevice device = this.getDeviceById(deviceId);

        List<EIDeviceEndPoint> endPoints = device.getDeviceEndPoints();
        for (EIDeviceEndPoint endPoint : endPoints) {
            this.deleteEndPoint(endPoint.getEndPointId());
        }
        DeviceVO devicevo = devicedao.findById(deviceId);
        this.deviceSerialnoCache.remove(devicevo.getSerialno());
        this.deviceCache.remove(devicevo.getDeviceid());
        this.devicemacadressCache.remove(devicevo.getMacaddress());
        devicedao.delete(devicevo);

    }

    public void deleteZNodeById(String nodeId) {

        EIZNode znode = this.getZNodeById(nodeId);
        List<EIAlarm> alarms = znode.getAlarmList();
        for (EIAlarm alarm : alarms) {
            this.deleteAlarmById(alarm.getAlarmid());
        }

        List<EIScene> scenes = znode.getSceneList();
        for (EIScene scene : scenes) {
            this.deleteScene(scene.getSceneid());
        }

        ZNodeDAO znodeDAO = new ZNodeDAO();
        ZNodeVO node = znodeDAO.findById(nodeId);
        if (node != null) {
            znodeDAO.delete(node);
            znodeCache.remove(node.getZnodeid());
        }
    }

    public EIZNode getZNodeById(String nodeId) {
        EIZNode znode = null;
        ZNodeVO znodevo = znodeCache.get(nodeId);
        if (znodevo == null) {
            ZNodeDAO znodeDAO = new ZNodeDAO();
            ZNodeVO vo = znodeDAO.findById(nodeId);
            if (vo != null) {
                znode = new DBZNode(vo);
                znodeCache.put(nodeId, vo);
            }

        } else {
            znode = new DBZNode(znodevo);
        }

        return znode;
    }

    public void updateZNode(EIZNode node, boolean indb) {

        List<EIAlarm> alarms = node.getAlarmList();
        for (EIAlarm alarm : alarms) {
            this.updateAlarm(alarm);
        }

        List<EIScene> scenes = node.getSceneList();
        for (EIScene scene : scenes) {
            this.updateScene(scene);
        }
        DBZNode dbznode = (DBZNode) node;
        if (indb) {
            ZNodeDAO znodeDAO = new ZNodeDAO();

            znodeDAO.update(dbznode.getVo());
        }

        znodeCache.put(node.getZnodeid(), dbznode.getVo());
        JDSActionContext.getActionContext().getContext().remove("status[" + node.getZnodeid() + "]");
        JDSActionContext.getActionContext().getContext().remove("createId[" + node.getZnodeid() + "]");
    }

    public EIZNode createRootZNode(String endpointid, String placeId, String createuiserid, ZNodeZType type) {

        EIDeviceEndPoint endPoint = this.getEndPoindById(endpointid);
        EIZNode znode = this.getZNodeByDeviceId(endPoint.getDeviceId(), createuiserid);
        if (znode == null) {
            // List<EIZNode> znodes = endPoint.getAllZNodes();
            EIPlace place = this.getPlaceById(placeId);
            ZNodeVO snode = new ZNodeVO();
            snode.setZnodeid(UUID.randomUUID().toString());
            snode.setEndpointid(endpointid);
            snode.setCreateuiserid(createuiserid);
            znode = new DBZNode(snode);

            if (endPoint != null && endPoint.getDevice() != null) {
                snode.setDeviceid(endPoint.getDevice().getDeviceid());
                snode.setZtype(type.getType());
                snode.setSensortype(endPoint.getSensortype().getType());
                snode.setMacaddress(endPoint.getNwkAddress());
                snode.setMasterkey(endPoint.getProfileid());

                // 主节点
                snode.setParentid(snode.getZnodeid());
                snode.setName(endPoint.getName());

                ZNodeDAO dao = new ZNodeDAO();
                dao.insert(snode);

                znodeCache.put(znode.getZnodeid(), snode);
                endPoint.addZNode(znode);

            }

        }

        return znode;

    }

    public List<EIZNode> getAllChildZNode(String parentNodeId) {
        ZNodeDAO znodeDAO = new ZNodeDAO();
        List<ZNodeVO> nodeList = znodeDAO.findByParentid(parentNodeId);
        List<EIZNode> ndoes = new ArrayList<EIZNode>();

        for (ZNodeVO cnode : nodeList) {
            EIZNode ccnode = this.getZNodeById(cnode.getZnodeid());
            if (ccnode != null) {
                ndoes.add(ccnode);
            }
        }
        return ndoes;
    }

    public EIZNode createChildZNode(String parentNodeId, String endPointId) {
        EIZNode pnode = this.getZNodeById(parentNodeId);
        EIDeviceEndPoint endPoint = this.getEndPoindById(endPointId);
        List<EIZNode> childnodes = pnode.getAllZNodes();

        EIZNode znode = null;

        for (EIZNode childnode : childnodes) {
            if (childnode != null && childnode.getEndPointid() != null && childnode.getEndPointid().equals(endPointId)) {
                znode = childnode;
                continue;
            }
        }

        if (znode == null) {
            ZNodeVO vo = new ZNodeVO();
            vo.setZnodeid(UUID.randomUUID().toString());
            vo.setEndpointid(endPointId);
            vo.setParentid(parentNodeId);
            vo.setCreateuiserid(pnode.getCreateuiserid());
            vo.setChannel(pnode.getChannel());

            vo.setDeviceid(endPoint.getDevice().getDeviceid());

            if (parentNodeId.equals(endPoint.getDevice().getDeviceid())) {
                vo.setZtype(ZNodeZType.GATEWAY.getType());
            } else if (pnode.getZtype().equals(ZNodeZType.SHARE.getType())) {
                vo.setZtype(pnode.getZtype());
            } else {
                vo.setZtype(endPoint.getSensortype().getZnodetype());
            }
            vo.setMacaddress(endPoint.getNwkAddress());
            vo.setMasterkey(endPoint.getProfileid());
            vo.setSensortype(endPoint.getSensortype().getType());
            vo.setName(endPoint.getSensortype().getName());

            ZNodeDAO dao = new ZNodeDAO();
            dao.insert(vo);
            znode = new DBZNode(vo);
            pnode.addZNode(znode);
            endPoint.addZNode(znode);

            znodeCache.put(vo.getZnodeid(), vo);
            JDSActionContext.getActionContext().getContext().remove("status[" + znode.getZnodeid() + "]");
            JDSActionContext.getActionContext().getContext().remove("createId[" + znode.getZnodeid() + "]");

        } else if (znode.getEndPointid() == null) {
            znode.setEndPointid(endPointId);
            this.updateZNode(znode, true);
        }

        return znode;
    }

    public EIZNode getZNodeByDeviceId(String deviceId, String userId) {

        EIZNode node = null;
        ZNodeDAO znodeDAO = new ZNodeDAO();
        ZNodeVO snode = new ZNodeVO();
        snode.setDeviceid(deviceId);
        snode.setCreateuiserid(userId);

        List<ZNodeVO> nodeList = znodeDAO.findByExample(snode);
        if (nodeList.size() > 0) {
            node = this.getZNodeById(nodeList.get(0).getZnodeid());

        }

        return node;

    }

    public List<EIZNode> getZNodesByDeviceId(String deviceid) {
        ZNodeDAO znodeDAO = new ZNodeDAO();

        List<ZNodeVO> nodevoList = znodeDAO.findByDeviceid(deviceid);

        List<EIZNode> ndoes = new ArrayList<EIZNode>();
        for (ZNodeVO cnode : nodevoList) {

            EIZNode ccnode = this.getZNodeById(cnode.getZnodeid());
            if (ccnode != null) {
                ndoes.add(ccnode);
            }

        }
        return ndoes;
    }

    public List<EIZNode> findZNodeByCreateId(String userId) {
        ZNodeDAO znodeDAO = new ZNodeDAO();
        List<ZNodeVO> nodevoList = znodeDAO.findByCreateuiserid(userId);
        List<EIZNode> ndoes = new ArrayList<EIZNode>();
        for (ZNodeVO cnode : nodevoList) {
            EIZNode ccnode = this.getZNodeById(cnode.getZnodeid());
            if (ccnode != null) {
                ndoes.add(ccnode);
            }

        }
        return ndoes;
    }

    public EIDevice createDevice(String serialno, String macaddress, Integer devicetype, String factory, String bindingAccount) {

        EIDevice parentDevice = this.getDeviceById(bindingAccount);
        if (factory == null) {
            factory = parentDevice.getFactory();
        }

        EIDevice sensorDevice = getDeviceBySerialno(serialno);

        if (sensorDevice == null) {
            DeviceDAO devicedao = new DeviceDAO();
            DeviceVO devicevo = new DeviceVO();
            if (devicetype == null) {
                String name = this.getSensoTypeByNo(devicetype).getName();
                devicevo.setName(name);
            }
            devicevo.setDeviceid(UUID.randomUUID().toString());
            devicevo.setSerialno(serialno);
            devicevo.setMacaddress(macaddress);

            devicevo.setFactory(factory);
            devicevo.setBindingaccount(bindingAccount);
            devicevo.setDevicetype(devicetype);
            devicevo.setAppaccount(parentDevice.getAppaccount());
            devicevo.setBatch(parentDevice.getBatch());
            devicevo.setChannel(parentDevice.getChannel());
            devicevo.setSubsyscode(parentDevice.getSubsyscode());
            devicevo.setStates(DeviceStatus.ONLINE.getCode());
            devicevo.setAddtime(System.currentTimeMillis());
            devicedao.insert(devicevo);

            sensorDevice = new DBDevice(devicevo);
            parentDevice.addChildDevice(sensorDevice);
        } else {

            sensorDevice.setFactory(factory);
            sensorDevice.setSerialno(serialno);
            sensorDevice.setMacaddress(macaddress);
            sensorDevice.setBindingaccount(bindingAccount);
            sensorDevice.setAppaccount(parentDevice.getAppaccount());
            sensorDevice.setBatch(parentDevice.getBatch());
            sensorDevice.setChannel(parentDevice.getChannel());
            sensorDevice.setSubsyscode(parentDevice.getSubsyscode());
            sensorDevice.setStates(DeviceStatus.ONLINE.getCode());
            parentDevice.addChildDevice(sensorDevice);

        }

        this.updateDevice(sensorDevice);
        return sensorDevice;
    }

    public List<EIZNode> getZNodesByEndPointId(String endPoindId) {
        ZNodeDAO znodeDAO = new ZNodeDAO();
        List<ZNodeVO> nodeList = znodeDAO.findByEndPointid(endPoindId);

        List<EIZNode> ndoes = new ArrayList<EIZNode>();

        for (ZNodeVO cnode : nodeList) {

            EIZNode ccnode = this.getZNodeById(cnode.getZnodeid());
            if (ccnode != null) {
                ndoes.add(ccnode);
            }

        }
        return ndoes;
    }


    public EIPlace createRootPlace(String name, String parentId, String personId) {
        PlaceDAO placeDAO = new PlaceDAO();
        PlaceVO placevo = new PlaceVO();
        placevo.setPlaceid(parentId);
        placevo.setName(name);
        placevo.setUserid(personId);
        placevo.setParentid(parentId);
        placeDAO.insert(placevo);

        EIPlace place = new DBPlace(placevo);
        placeCache.put(placevo.getPlaceid(), placevo);
        return place;
    }

    public void updatePlace(EIPlace place) {
        List<EIArea> areas = new ArrayList<EIArea>();
        for (EIArea area : areas) {
            this.updateArea(area);
        }
        if (this.getPlaceById(place.getParentId()) != null) {
            this.getPlaceById(place.getParentId()).addChild(place);
        }
        DBPlace dbPlace = (DBPlace) place;
        PlaceDAO placeDAO = new PlaceDAO();
        placeDAO.update(dbPlace.getVo());

        placeCache.put(place.getPlaceid(), dbPlace.getVo());
    }

    public Set<String> getAreaIdsByPlaceId(String placeId) {
        String idsjson = this.getAllAreaIdCache().get(placeId);
        List<String> areaIds = new ArrayList<>();
        if (idsjson == null) {
            AreaDAO areaDAO = new AreaDAO();
            List<AreaVO> dbareas = areaDAO.findByPlaceId(placeId);
            for (AreaVO area : dbareas) {
                areaIds.add(area.getAreaid());
            }

            idsjson = JSONObject.toJSONString(areaIds);
            this.getAllAreaIdCache().put(placeId, idsjson);
        }
        areaIds = JSONArray.parseArray(idsjson, String.class);
        return new LinkedHashSet<String>(areaIds);
    }

    public List<EIArea> getAreasByPlaceId(String placeId) {

        Set<String> ids = getAreaIdsByPlaceId(placeId);
        List<EIArea> areas = new ArrayList<EIArea>();
        for (String areaid : ids) {
            areas.add(this.getAreaById(areaid));
        }
        return areas;
    }

    public List<EIZNode> getZNodesByPlaceId(String placeid, Integer type) {
        ZNodeDAO znodeDAO = new ZNodeDAO();

        ZNodeVO vo = new ZNodeVO();

        vo.setSensortype(type);
        List<ZNodeVO> nodeList = znodeDAO.findByExample(vo);

        List<EIZNode> ndoes = new ArrayList<EIZNode>();

        for (ZNodeVO cnodevo : nodeList) {
            EIZNode ccnode = this.getZNodeById(cnodevo.getZnodeid());
            if (ccnode != null) {
                ndoes.add(ccnode);
            }

        }
        return ndoes;
    }


    @Override
    public Set<String> findGWDevicesByFactory(String factoryName) {

        DeviceDAO devicedao = new DeviceDAO();

        Set<String> deviceList = new LinkedHashSet<>();

        List<DeviceVO> devicevoList = devicedao.findDeviceByType(factoryName, 0);
        for (DeviceVO vo : devicevoList) {
            deviceList.add(vo.getDeviceid());
        }

        return deviceList;
    }

    @Override
    public EISensortype updateSensorType(EISensortype sensortype) {
        SensortypeDAO sensortypeDAO = new SensortypeDAO();
        DBSensortype dbSensortype = (DBSensortype) sensortype;

        List<EISensortype> types = new ArrayList<EISensortype>();

        SensortypeVO vo = sensortypeDAO.findById(sensortype.getTypeid());
        vo.setAlarmurl(sensortype.getAlarmurl());
        vo.setColor(sensortype.getColor());
        vo.setDatalisturl(sensortype.getDatalisturl());
        vo.setHtmltemp(sensortype.getHtmltemp());
        vo.setHisdataurl(sensortype.getHisdataurl());
        vo.setDeviceid(sensortype.getDeviceid());
        vo.setIcon(sensortype.getIcon());
        vo.setIcontemp(sensortype.getIcontemp());
        vo.setType(sensortype.getType());
        vo.setName(sensortype.getName());

        this.sensorTypeIdCache.remove(vo.getTypeid());
        this.sensorTypeNoCache.remove(vo.getType().toString());

        sensortypeDAO.update(dbSensortype.getVo());
        sensortype = getSensoTypeById(vo.getTypeid());


        return sensortype;
    }

    @Override
    public void deleteSensorType(Integer typeno) {
        SensortypeDAO sensortypeDAO = new SensortypeDAO();
        SensortypeVO vo = sensortypeDAO.findBynO(typeno).get(0);
        sensortypeDAO.delete(vo);
    }


    public List<EIZNode> findZNodesByCreateId(String userId) {
        ZNodeDAO znodeDAO = new ZNodeDAO();
        List<ZNodeVO> nodeList = znodeDAO.findByCreateuiserid(userId);

        List<EIZNode> ndoes = new ArrayList<EIZNode>();

        for (ZNodeVO vo : nodeList) {
            EIZNode ccnode = this.getZNodeById(vo.getZnodeid());
            if (ccnode != null) {
                ndoes.add(ccnode);
            }
        }
        return ndoes;
    }

    public EIDevice createRootDevice(String deviceId, String serialno, String macaddress, String factoryName, String version) throws HomeException {
        EIDevice gwDevice = null;
        logger.info("createRootDevice:注册网关,Gateway:deviceId=" + deviceId + "serialno=" + serialno);
        if (deviceId != null) {
            gwDevice = this.getDeviceById(deviceId);
        } else if (serialno != null && !serialno.equals("")) {

            if (serialno.trim().length() > 16) {
                serialno = serialno.trim().substring(0, 16);
            }

            EIDevice device = getDeviceBySerialno(serialno);
            if (device != null && device.getDevicetype().equals(0)) {
                gwDevice = device;
            }
        }

        DeviceDAO devicedao = new DeviceDAO();

        if (gwDevice == null) {
            if (serialno == null || serialno.equals("")) {
                throw new HomeException("can not create device: serialno is null");
            }

            if (deviceId == null) {
                deviceId = UUID.randomUUID().toString();
            }

            DeviceVO devicevo = new DeviceVO();
            devicevo.setDeviceid(deviceId);
            devicevo.setSerialno(serialno);
            devicevo.setFactory(factoryName);
            devicevo.setMacaddress(macaddress);
            devicevo.setBindingaccount(deviceId);

            devicevo.setName("网关(" + serialno + ")");
            devicevo.setDevicetype(0);
            devicevo.setAppaccount(deviceId);
            devicevo.setStates(DeviceStatus.ONLINE.getCode());
            devicevo.setSubsyscode(factoryName);
            devicevo.setAddtime(System.currentTimeMillis());
            devicedao.insert(devicevo);

            gwDevice = new DBDevice(devicevo);
            this.deviceCache.put(devicevo.getDeviceid(), devicevo);
            this.deviceSerialnoCache.put(devicevo.getSerialno(), devicevo.getDeviceid());
            this.devicemacadressCache.put(devicevo.getMacaddress(), devicevo.getDeviceid());
        } else {
            if (serialno != null && !serialno.equals("")) {
                gwDevice.setSerialno(serialno);
            }
            if (macaddress != null && !macaddress.equals("")) {
                gwDevice.setMacaddress(macaddress);
            }
            gwDevice.setBindingaccount(gwDevice.getDeviceid());
            if (factoryName != null && !factoryName.equals("")) {
                gwDevice.setFactory(factoryName);

            }
            if (version != null && !version.equals("")) {
                gwDevice.setBatch(version);
            }

            gwDevice.setStates(DeviceStatus.ONLINE.getCode());
            DBDevice dbdevice = (DBDevice) gwDevice;
            this.updateDevice(gwDevice);

            //   devicedao.update(dbdevice.getDevicevo());

        }

        return gwDevice;
    }

    public void removeChildDevice(String bindingAccount, String chileDeviceId) {
        EIDevice parentDevice = this.getDeviceById(bindingAccount);
        parentDevice.removeChildDevice(chileDeviceId);

    }

    @Override
    public EISensortype createSensorType() {
        SensortypeDAO sensortypeDAO = new SensortypeDAO();
        List<EISensortype> types = new ArrayList<EISensortype>();
        SensortypeVO vo = new SensortypeVO();
        vo.setTypeid(UUID.randomUUID().toString());
        vo.setDeviceid("default");
        vo.setType(200);
        sensortypeDAO.insert(vo);
        this.sensorTypeIdCache.put(vo.getTypeid(), vo);
        return new DBSensortype(vo);
    }


    public Cache<String, AreaVO> getAreaCache() {
        return areaCache;
    }

    public Cache<String, PlaceVO> getPlaceCache() {
        return placeCache;
    }

    public Cache<String, SensortypeVO> getSensorTypeNoCache() {
        return sensorTypeNoCache;
    }

    public Cache<String, SensortypeVO> getSensorTypeIdCache() {
        return sensorTypeIdCache;
    }

    public Cache<String, AlarmVO> getAlarmCache() {
        return alarmCache;
    }

    public Cache<String, SceneVO> getSceneCache() {
        return sceneCache;
    }

    public String getCacheKey() {
        return cacheKey;
    }

    public Cache<String, DeviceVO> getDeviceCache() {
        return deviceCache;
    }

    public Cache<String, String> getDeviceSerialnoCache() {
        return deviceSerialnoCache;
    }

    public Cache<String, DeviceEndPointVO> getEndPointCache() {
        return endPointCache;
    }

    public Cache<String, String> getEndPointSerialnoCache() {
        return endPointSerialnoCache;
    }

    public Cache<String, String> getDevicemacadressCache() {
        return devicemacadressCache;
    }

    public Cache<String, String> getAllEPIdCache() {
        return allEPIdCache;
    }

    public Cache<String, String> getAllChildIdCache() {
        return allChildIdCache;
    }

    public Cache<String, ZNodeVO> getZnodeCache() {
        return znodeCache;
    }

    public Cache<String, String> getCurrValueCache() {
        return currValueCache;
    }

    public Cache<String, String> getAllZNodeIdCache() {
        return allZNodeIdCache;
    }


    public Cache<String, String> getAllAreaIdCache() {
        return allAreaIdCache;
    }

    public Cache<String, String> getZNodeRefZNodeCache() {
        return zNodeRefZNodeCache;
    }

    public Cache<String, String> getZNodeRefAlarmCache() {
        return zNodeRefAlarmCache;
    }

    public Cache<String, String> getAllSceneIdCache() {
        return allSceneIdCache;
    }

    @Override
    public Cache<String, String> getPlaceRefChildIdCache() {
        return placeRefChildIdCache;
    }


    public void clearPlaceCache(String placeId) {

        placeRefChildIdCache.remove(placeId);
        allAreaIdCache.remove(placeId);
        placeCache.remove(placeId);
    }

    @Override
    public List<EIPlace> getChildPlaces(String placeId) {
        Set<String> palceIds = this.getChildPlaceIds(placeId);
        List<EIPlace> palces = new ArrayList<EIPlace>();
        for (String chidplaceId : palceIds) {
            if (chidplaceId != null) {
                EIPlace place = manager.getPlaceById(chidplaceId);
                if (place != null) {
                    palces.add(place);
                }
            }
        }
        return palces;
    }

    @Override
    public Set<String> getChildPlaceIds(String placeId) {
        String idsjson = manager.getPlaceRefChildIdCache().get(placeId);
        List<String> palceIds = new ArrayList<String>();
        if (idsjson == null) {
            List<String> childPlaceIds = new ArrayList<String>();
            PlaceDAO placeDAO = new PlaceDAO();
            List<PlaceVO> palces = placeDAO.findByParentid(placeId);
            for (PlaceVO placeVO : palces) {
                childPlaceIds.add(placeVO.getPlaceid());
            }
            idsjson = JSONObject.toJSONString(childPlaceIds);
            manager.getPlaceRefChildIdCache().put(placeId, idsjson);
        }
        palceIds = JSONArray.parseArray(idsjson, String.class);
        return new LinkedHashSet<>(palceIds);
    }


}
